﻿#region << 文件说明 >>

/*----------------------------------------------------------------
 * 命名空间：Vampirewal.Core.WPF.Theme.Common
 * 唯一标识：604120a3-3700-4026-bebc-050fcf338494
 * 文件名：TouchEventCommands
 *
 * 创建者：杨程
 * 电子邮箱：235160615@qq.com
 * 创建时间：2023/9/25 14:38:49
 * 版本：V1.0.0
 * 描述：
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/

#endregion << 文件说明 >>

using System.Reflection;
using System.Reflection.Emit;

namespace Vampirewal.Core.WPF.Theme;

public interface IEventAction
{
    string EventName { get; }
}

/// <summary>
/// MVVM事件绑定，详细看CSDN博客
/// <para >此处代码引用自 若汝棋茗</para>
/// <para >CSDN博客：https://blog.csdn.net/qq_40374647/article/details/127651804?spm=1001.2014.3001.5501</para>
/// <para >哔哩哔哩视频：https://space.bilibili.com/94253567</para>
/// <para >Gitee源代码仓库：https://gitee.com/RRQM_Home</para>
/// <para >Github源代码仓库：https://github.com/RRQM</para>
/// <para >API首页：https://www.yuque.com/rrqm/touchsocket/index</para>
/// <para >交流QQ群：234762506</para>
/// </summary>
public static class TouchEventCommands
{
    // Using a DependencyProperty as the backing store for Events.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty EventsProperty =
        DependencyProperty.RegisterAttached("Events", typeof(IEnumerable<IEventAction>), typeof(TouchEventCommands), new PropertyMetadata(null, OnCommandChanged));

    public static IEnumerable<IEventAction> GetEvents(DependencyObject obj)
    {
        return (IEnumerable<IEventAction>)obj.GetValue(EventsProperty);
    }

    public static void SetEvents(DependencyObject obj, IEnumerable<IEventAction> value)
    {
        obj.SetValue(EventsProperty, value);
    }

    private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is IEnumerable eventActions)
        {
            foreach (IEventAction eventAction in eventActions)
            {
                if (!string.IsNullOrEmpty(eventAction.EventName))
                {
                    EventInfo eventInfo = d.GetType().GetEvent(eventAction.EventName);
                    if (eventInfo == null)
                    {
                        throw new Exception($"没有找到名称为{eventAction.EventName}的事件");
                    }
                    Delegate @delegate = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventAction, "Event");
                    //Delegate @delegate2 = eventAction.Begin(eventInfo.EventHandlerType, typeof(object), typeof(MouseButtonEventArgs));
                    //Delegate @delegate = DelegateBuilder.CreateDelegate(eventAction, "Event", eventInfo.EventHandlerType, BindingFlags.NonPublic);
                    eventInfo.AddEventHandler(d, @delegate);
                }
                else
                {
                    throw new Exception($"事件名不能为空");
                }
            }
        }
    }
}

public class EventAction<TSender, TE> : IEventAction
{
    private readonly Action<TSender, TE> action;

    private readonly string eventName;

    public EventAction(string eventName, Action<TSender, TE> action)
    {
        this.eventName = eventName;
        this.action = action;
    }

    public string EventName => this.eventName;

    private void Event(TSender sender, TE e)
    {
        this.action?.Invoke(sender, e);
    }
}

public class EventAction<TE> : IEventAction
{
    private readonly Action<object> action;

    private readonly Action<TE> action2;

    private readonly string eventName;

    public EventAction(string eventName, Action<object> action)
    {
        this.eventName = eventName;
        this.action = action;
    }

    public EventAction(string eventName, Action<TE> action)
    {
        this.eventName = eventName;
        this.action2 = action;
    }

    public string EventName => this.eventName;

    private void Event(object sender, TE e)
    {
        this.action?.Invoke(sender);
        this.action2?.Invoke(e);
    }
}
